package com.fjzn.detect.config.web.interceptor;

import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.fjzn.detect.common.constants.Constants;
import com.fjzn.detect.common.enums.web.ResponseStatus;
import com.fjzn.detect.config.web.filter.RepeatedlyRequestWrapper;


import com.fjzn.detect.core.result.CommonRespUtils;
import com.fjzn.detect.core.result.ResponseResult;
import com.fjzn.detect.core.utils.sign.SignUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.net.URLDecoder;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;

/**
 * 签名拦截器
 *
 * @author yzh
 * @since 2021年04月25日16:43:49
 *
 */
@Component
public class ApiSignAccessHandlerInterceptor extends HandlerInterceptorAdapter {

    private static  final Charset CHARSET = StandardCharsets.UTF_8;

    final private static String TIMESTAMP = "x-time";
    final private static String REQUESTID = "x-request-id";
    final private static String TERMINALID = "x-terminal-id";
    final private static String CHANNEL = "x-channel";
    final private static String LANG = "x-lang";
    final private static String AUTH= "Authorization";
    final private static String SIGN = "x-sign";
    final private static String URL = "url";
    final private static String BODY = "body";

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {

        Map<String,Object> parm = new HashMap<>();
        parm.put(TIMESTAMP,request.getHeader(TIMESTAMP));
        parm.put(REQUESTID,request.getHeader(REQUESTID));
        parm.put(TERMINALID,request.getHeader(TERMINALID));
        parm.put(CHANNEL,request.getHeader(CHANNEL));
        parm.put(AUTH,request.getHeader(AUTH));
        parm.put(LANG,request.getHeader(LANG));
        String sign = request.getHeader(SIGN);
        String url = URLDecoder.decode(getUrl(request),StandardCharsets.UTF_8.toString());
        String body = "";
        if(isFormPost(request)){
            body = toFormSignBody(request);
        }else{
            body = getRequestBody(request);
        }
        parm.put(URL,url);
        parm.put(BODY, StringUtils.isEmpty(body) ? null : body);
        String serSign = SignUtils.sign(parm);
        if(!(StrUtil.isNotBlank(sign) && sign.compareTo(serSign) == 0)){
            CommonRespUtils.returnERR(ResponseResult.error(ResponseStatus.签名失败),request,response);
            return false;
        }
        return true;
    }

    private String getReqFormData(HttpServletRequest request){
        request.getParameterMap().forEach((key,val)->{
            System.out.println(request.getParameter(key));
        });
       return null;
    }

    private String getUrl(HttpServletRequest request){
        String query  = request.getQueryString();
        if(StrUtil.isNotBlank(query)){
          return  request.getRequestURI()+ "?"+query;
        }
        return request.getRequestURI();
    }

    private String getRequestBody(HttpServletRequest request){
        if(request instanceof RepeatedlyRequestWrapper && handleRequestMethod(request)){
            RepeatedlyRequestWrapper requestWrapper = (RepeatedlyRequestWrapper)request;
            String body = requestWrapper.getPostBodyAsString();
            return body;
        }
        return "";
    }

    private boolean handleRequestMethod(HttpServletRequest request){
        return "POST".compareToIgnoreCase(request.getMethod()) == 0 ||
                "PUT".compareToIgnoreCase(request.getMethod()) == 0 ;
    }

    private boolean isFormPost(HttpServletRequest request){
        return request instanceof RepeatedlyRequestWrapper && ((RepeatedlyRequestWrapper)request).isFormPost();
    }

    private String toFormSignBody(HttpServletRequest request){
        if(request instanceof RepeatedlyRequestWrapper){
            RepeatedlyRequestWrapper requestWrapper = (RepeatedlyRequestWrapper)request;
            Map<String,String[]> paramMap = requestWrapper.getBodyparameterMap();
            if(paramMap != null && !paramMap.isEmpty()){
                Map<String,Object> param = new HashMap<>();
                paramMap.forEach((key,val)->{
                    if(val == null){
                        param.put(key,"");
                    }else{
                        if(val.length ==  1){
                            param.put(key,val[0]);
                        }else {
                            param.put(key, JSON.toJSONString(val));
                        }
                    }
                });
                return SignUtils.sortParam(param);
            }
        }
        return  "";
    }

    /**
     * 获取请求token
     *
     * @param request
     * @return token
     */
    private String getToken(HttpServletRequest request)
    {
        String token = request.getHeader(AUTH);
        if (StringUtils.isNotEmpty(token) && token.startsWith(Constants.TOKEN_PREFIX))
        {
            token = token.replace(Constants.TOKEN_PREFIX, "");
        }
        return token;
    }

}
